﻿//1. 参数数组
//params 关键字声明
// public int Sum(params int[] sum){...}
// 不能与 ref/out 组合使用
using System.Diagnostics;
using System.Reflection;

Console.WriteLine($"平均分：{Calculate(85, 90, 76)}");
Console.WriteLine($"平均分：{Calculate()}");

int[] scores = {92, 88, 95};
//编译器自动转换为 new int[] {92, 88, 95}
Console.WriteLine($"平均分：{Calculate(scores)}");

#region 参数数组实现 
    static double Calculate(params int[] grades){
        if(grades == null || grades.Length == 0){
            Console.WriteLine("未输入任何成绩");
            return 0;
        } 
        int sum = 0;
        foreach(int grade in grades){
            sum += grade;
        }
        return (double)sum/grades.Length;
    }
#endregion

//2. 栈帧
// 每个方法调用时，CLR会在调用栈上分配一个栈帧
// 包含：
//     返回地址：方法结束后回到哪个指令
//     局部变量：包括值类型变量和对象引用
//     栈指针：当前栈顶位置
//     异常处理信息
Console.WriteLine("主方法开始");
MethodA();
Console.WriteLine("主方法结束");

#region 栈帧分析实现
    static void MethodA(){
        Console.WriteLine("进入A方法");
        MethodB();
        Console.WriteLine("离开A方法");
    }
    static void MethodB(){
        Console.WriteLine("进入B方法");
        PrintStackFrams();
        Console.WriteLine("离开B方法");
    }

    static void PrintStackFrams(){
        //创建包含源代码信息的堆栈跟踪
        StackTrace stackTrace = new StackTrace(true);
        Console.WriteLine("\n当前调用栈深度：" + stackTrace.FrameCount);
        Console.WriteLine("-----------------------------------------");
        for(int i = 0; i < stackTrace.FrameCount; i++){
            //StackFrame包含方法、文件、行号等元数据
            StackFrame frame = stackTrace.GetFrame(i);
            MethodBase method = frame.GetMethod();

            Console.WriteLine($"|层级：{i}");
            Console.WriteLine($"|方法：{method.DeclaringType?.Name}.{method.Name}");
            Console.WriteLine($"|文件：{frame.GetFileName()??"未知"}");
            Console.WriteLine($"|行号：{frame.GetFileLineNumber()}");
            Console.WriteLine("-----------------------------------------");
        }
    }
#endregion


//3. 递归
//  (1) 基准条件
//      必须存在明确的递归终止条件，防止无限递归；
//  (2) 递归步骤
//      每次递归必须向基准条件推进，通过缩小问题规模实现；

var root = new TreeNode<char>('A');
root.Left = new TreeNode<char>('B');
root.Right = new TreeNode<char>('C');
root.Left.Left = new TreeNode<char>('D');
root.Left.Right = new TreeNode<char>('E');
root.Right.Right = new TreeNode<char>('F');

Console.WriteLine("前序遍历结果：");
Pre(root);

#region 递归算法实现

    static void Pre<T>(TreeNode<T>? node){
        if(node == null) return;
        Console.Write(node.Data + " ");
        Pre(node.Left);
        Pre(node.Right);
    }
    class TreeNode<T>{
        public T Data {get; set; }
        public TreeNode<T>? Left{get; set;}
        public TreeNode<T>? Right{get; set;}

        public TreeNode(T data){
            Data = data;
            Left = null;
            Right = null;
        }
    }

#endregion